package com.sunny.design.observer.events;

import com.google.common.collect.Maps;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * 观察者模式(Observer Pattern)
 *  观察者模式定义了对象之间的一对多 依赖，让多个观察者对象同时监听一个主体对象，当主体对象 发生变化时，它的所有依赖者(观察者)都会收到通知并更新。
 *  属于行为型模式。
 *
 *  观察者模式有时也叫做发布订阅模式
 *
 * 监听器，它就是观察者的桥梁
 *
 * @author Sunny
 * @date 2020/1/15
 */
class EventListener {

    /**
     * JDK 底层的 Listener 通常也是这样来设计的
     */
    private Map<String, Event> events = Maps.newHashMap();

    void addListener(String eventType, Object target) {
        try {
            this.addListener(eventType, target, target.getClass().getMethod("on" + toUpperFirstCase(eventType), Event.class));
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    /**
     * 注册事件
     *
     * @param eventType 事件类型
     * @param target    事件触发后要通知谁
     * @param callback  回调方法
     */
    private void addListener(String eventType, Object target, Method callback) {
        events.put(eventType, new Event(target, callback));
    }

    private void trigger(Event event) {
        event.setSource(this);
        event.setTime(System.currentTimeMillis());

        try {
            if (event.getCallback() != null) {
                //用反射调用它的回调函数
                event.getCallback().invoke(event.getTarget(), event);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    void trigger(String trigger) {
        if (events.containsKey(trigger)) {
            Event event = events.get(trigger);
            event.setTrigger(trigger);
            trigger(event);
        }
    }

    /**
     * 首字母大写
     *
     * @param str 字符串
     */
    private String toUpperFirstCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }
}
